package com.navinfo.opentsp.platform.computing.analysis.service;

import com.navinfo.opentsp.platform.computing.analysis.entity.cleanAsh.CleanAshEvent;
import com.navinfo.opentsp.platform.computing.analysis.entity.cleanAsh.OutData;
import com.navinfo.opentsp.platform.computing.analysis.entity.cleanAsh.PointForCleanAsh;

import java.io.Serializable;
import java.util.OptionalDouble;
import java.util.stream.IntStream;

/**
 * DPF清灰事件 算法
 */
public class CleanAshAlgorithmService implements Serializable {
    private static final int NUM_OF_AVG = 10;
    private int cleanAshThreshold;
    private int cleanAshDiffThreshold;

    public CleanAshAlgorithmService(int cleanAshThreshold, int cleanAshDiffThreshold) {
        this.cleanAshThreshold = cleanAshThreshold;
        this.cleanAshDiffThreshold = cleanAshDiffThreshold;
    }

    public void dealPoint(PointForCleanAsh point, OutData outData) {
        Integer dpfAshLoading = null;
        if (isAccOn(point)) {
            dpfAshLoading = point.getDpfAshLoading();
        }
        // 当出现连续3个点acc=on且灰载量<3%
        if (isBelow(dpfAshLoading) && isBelow(outData.getAshLoadPre1()) && isBelow(outData.getAshLoadPre2())) {
            int[] ashLoads = outData.peek(NUM_OF_AVG);
            OptionalDouble avgVal = IntStream.of(ashLoads).average();
            if (avgVal.isPresent() && avgVal.getAsDouble() - dpfAshLoading > cleanAshDiffThreshold) {
                // 平均值与当前点灰载量差>50%
                CleanAshEvent newEvent = new CleanAshEvent();
                newEvent.setTid(outData.getTid());
                newEvent.setStartTime(point.getGpsTime());
                newEvent.setEndTime(point.getGpsTime());
                newEvent.setEngineRunningTime(point.getEngineRunningTime());
                newEvent.setTotalMileage(point.getGpsMileage());
                newEvent.setAshLoadingBef((int) avgVal.getAsDouble());
                newEvent.setAshLoadingAft(dpfAshLoading);
                outData.getOutEvents().add(newEvent);

                // 清灰事件条件满足一次后，清空缓存队列
                outData.clear();
            }
        }
        // 保存上一个点信息
        outData.shift(dpfAshLoading);
        outData.push(dpfAshLoading);
    }

    private boolean isAccOn(PointForCleanAsh point) {
        return point.getAccStatus() == 1;
    }

    private boolean isBelow(Integer a) {
        return a != null && a < cleanAshThreshold;
    }
}
